%%%-------------------------------------------------------------------
%%% @author Administrator
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 13. 1月 2020 14:14
%%%-------------------------------------------------------------------
-module(netWebServer).
-author("Administrator").

-behaviour(gen_server).

-include("../include/web.hrl").
-include("../include/logger.hrl").
-include("../include/game.hrl").
-include("../include/myshare.hrl").
%% API
-export([start_link/1, active_task/1, delete_task/1]).

%% gen_server callbacks
-export([init/1,
  handle_call/3,
  handle_cast/2,
  handle_info/2,
  terminate/2,
  code_change/3]).

-define(SERVER, ?MODULE).

-record(state, {socket}).

%%%===================================================================
%%% API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Starts the server
%%
%% @end
%%--------------------------------------------------------------------
-spec(start_link(Socket :: atom()) ->
  {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
start_link(Socket) ->
  gen_server:start_link(?MODULE, [Socket], [{timeout, ?Start_Link_TimeOut_ms}]).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Initializes the server
%%
%% @spec init(Args) -> {ok, State} |
%%                     {ok, State, Timeout} |
%%                     ignore |
%%                     {stop, Reason}
%% @end
%%--------------------------------------------------------------------
-spec(init(Args :: term()) ->
  {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term()} | ignore).
init([Socket]) ->
  ?DEBUG("netLoginServer init Socket=~p", [Socket]),
  process_flag(trap_exit, true),
  {ok, #state{socket = Socket}}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling call messages
%%
%% @end
%%--------------------------------------------------------------------
-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
    State :: #state{}) ->
  {reply, Reply :: term(), NewState :: #state{}} |
  {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
  {stop, Reason :: term(), NewState :: #state{}}).
handle_call(_Request, _From, State) ->
  {reply, ok, State}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling cast messages
%%
%% @end
%%--------------------------------------------------------------------
-spec(handle_cast(Request :: term(), State :: #state{}) ->
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), NewState :: #state{}}).

handle_cast(tcp_accept, State) ->
  io:format("tcp handler info accept client ~p~n", [State]),
  {noreply, State, ?TCP_TIMEOUT};

handle_cast(stop, State) ->
  {stop, normal, State};

handle_cast(_Request, State) ->
  {noreply, State}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling all non call/cast messages
%%
%% @spec handle_info(Info, State) -> {noreply, State} |
%%                                   {noreply, State, Timeout} |
%%                                   {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), NewState :: #state{}}).
handle_info({tcp, Socket, Data}, State) ->
  try
    erlang:put(receiveLS, true),
    ?INFO("receive tcp msg socket:~p data:~p", [Socket, Data]),
    case get(receiveLS) of
      true ->
        Content = jsx:decode(Data, [return_maps, {labels, atom}]),
        Code = maps:get(code, Content),
        NewData = maps:get(data, Content),
        R_msg = "{\"error\":0}",
        Return_msg =
          case Code of
            ?ACTIVE_TASK ->%激活新任务
              TaskId = maps:get(task_id, NewData),
              active_task(TaskId),
              R_msg;
            ?DELETE_TASK -> %删除任务
              TaskId = maps:get(task_id, NewData),
              delete_task(TaskId),
              R_msg;
            ?UPDATE_TASK -> %修改任务
              TaskId = maps:get(task_id, NewData),
              update_task(TaskId),
              R_msg;
            ?PLAYER_GAME_ROOM_STATE ->
              Account = maps:get(account, NewData),
              Game_id = maps:get(game_id, NewData),
              get_game_room_state(binary_to_list(Account), Game_id);
            ?KICKING ->
              Account = maps:get(account, NewData),
              ?DEBUG("kicking player account:~p", [Account]),
              PlayerPid = list_to_atom("pid_" ++ binary_to_list(Account)),
              PlayerPid ! {kicking},
              R_msg;
            _ -> ok
          end,
        gen_tcp:send(Socket, Return_msg),
        {noreply, State, ?TCP_TIMEOUT};
      false -> {stop, normal, State}
    end
  catch
    Class:Error:Stacktrace ->
      ?ERROR("webServer process class:~p,error:~p,stacktrace:~p",
        [Class, Error, Stacktrace]),
      {stop, normal, State}
  end;


handle_info({delete_task, Task_id}, State) ->
  ets:delete(?ETS_GAME_TASK, Task_id),
  {noreply, State};

handle_info({tcp_closed, _Socket}, State) ->
  ?INFO("tcp handler info ~p client ~p disconnected", [self(), State]),
  {stop, normal, State};

handle_info(timeout, State) ->
  ?INFO("tcp handler info ~p client connection timeout", [self()]),
  {stop, normal, State};

handle_info(_Info, State) ->
  {noreply, State}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any
%% necessary cleaning up. When it returns, the gen_server terminates
%% with Reason. The return value is ignored.
%%
%% @spec terminate(Reason, State) -> void()
%% @end
%%--------------------------------------------------------------------
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
    State :: #state{}) -> term()).
terminate(_Reason, #state{socket = Socket}) ->
  io:format("tcp handler terminate ~p~n", [_Reason]),
  (catch gen_tcp:close(Socket)),
  ok.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Convert process state when code is changed
%%
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
%% @end
%%--------------------------------------------------------------------
-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
    Extra :: term()) ->
  {ok, NewState :: #state{}} | {error, Reason :: term()}).
code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

%%%===================================================================
%%% Internal functions
%%%===================================================================
%激活新任务
active_task(TaskId) ->
  Rows = database:select_task(TaskId),
  case Rows of
    [] -> ok;
    [Row] -> client:add_task(Row)
  end,
  ok.
%删除任务
delete_task(TaskId) ->
  game_assist:delete_task(TaskId),
  erlang:send_after(60000, self(), {delete_task, TaskId}),
  ok.
%修改任务
update_task(TaskId) ->
  game_assist:update_ets_task(TaskId).

get_game_room_state(Account, Game_id) ->
  Map = web_assist:get_room_state(Account, Game_id),
  Json = binary_to_list(jsx:encode(Map)),
  ?DEBUG("get_game_room_state ret ~p", [Json]),
  Json.







